#ifndef _TELEMETRY_H
#define _TELEMETRY_H

//const QString FILE_SOURCE_NAME("ServConRawData.dat");
//const QString FILE_TARGET_NAME("ServConParsedForInflationUI.dat");
namespace TM {
    
const QString SYNC1 ("SM2-DG1GGH");
const QString SYNC2 ("ServConEOF");

// communication struct - Frames are sent with 5 Hz.
// some sensors are read faster, so there are more than one value in each frame
//Fr die Sensoren, die schneller als 5 Hz angefragt werden habe ich arrays eingebaut. 
//Der Index z�lt die Messungen (bei Druck z.B. zwei pro Frame, weil Drcke mit 10 Hz gemessen werden).
//Data types: alles unsigned, Status_Bits 32 Bit, Rest 16 bit. Syncs sind natrlich chars.

const int SYNC_LENGTH = 10;
const int PRESS_LENGTH = 2;
const int ACCEL_LENGTH = 10;
const int RATES_LENGTH = 10;

typedef enum ServConTypeMask{
	StatusLeftBoomStowed = 0x0,//need info
	StatusLeftBoomDeployed = 0x1,//stowed/deployed
	StatusRightBoomStowed = 0x2,//need info
	StatusRightBoomDeployed = 0x4,//stowed/deployed
	StatusBoomCameras =  0x8, //on/off
	StatusHoseClamp = 0x10,//: sep./not sep.
	StatusClampRing = 0x20,//: sep./not sep.
	BlossomPosition = 0x40, //: locked/not-locked
	StatusTankValve = 0x80,//: open/closed
	StatusInflationControlCommandSequence = 0x100,//: Running/not running
	StatusThrusterValve = 0x200,//: open/closed
	StatusMarkerLEDsOff = 0x400,//: 0x800on/off, strobe//need info
	StatusMarkerLEDsOn = 0x800,
	StatusMarkerLEDsStrobe = StatusMarkerLEDsOn&StatusMarkerLEDsOff,//don't know this, need info
	ServoStatusGroup1 = 0x1000,// (1bit per group): off, rotating//need info
	ServoStatusGroup2 = 0x2000,
	ServoStatusGroup3 = 0x4000,
	StatusBeacon = 0x8000,//: on/off
	CheckoutSCET = 0x10000,
	PodSCET = 0x20000,
	FlightSCET = 0x40000,
	StateMachineBit1 = 0x80000,
	StateMachineBit2 = 0x100000,
	StateMachineBit3 = 0x200000,
	StateMachineBit4 = 0x400000
};
const double BAT_PACK_ONE_BIT_RESOLUTION = 0.0625;
const double PCB_TEMP_ONE_BIT_RESOLUTION = 0.0625;
const double TEMPERATURE_ONE_BIT_RESOULTION = 1;// Kelvin
const double PRESSURE_ONE_BIT_RESOULTION = 1;// bar
const double ACCELERATION_ONE_BIT_RESOULTION = 1;// m/ss
const double RATE_ONE_BIT_RESOULTION = 1;// rad/s
const double VOLTAGE_ONE_BIT_RESOULTION = 1; //voltage
const double CURRENT_ONE_BIT_RESOULTION = 1; //Amperes
const double SCET_TIME_CONVERSION = 0.10;//scet time clicks to seconds (100ms per click)


//(minBITS + data/(MAXBITS-mINBITS))
//0x0000 + 0xac34)/(0x0FFF - 0x0000) * resolution
//
//bool isCSET(TypeMask mask)
//class Frame
//{
//	bool isCSET();
//	bool isCSET(const Frame& frame);
//}
//

typedef struct TM_ServCon_Frame_tag {

 quint8 sync1[SYNC_LENGTH];
 quint16 FrameCounter;//FrameCounter z�lt einfach die Frames der Reihe nach, damit wir merken wenn einer fehlt.
 quint16 Scet;//SCET ist die aktuelle "Uhrzeit" auf dem ServCon, z�lt in 0.1 sec Schritten hoch. Der von Hannes gewnschte SCET type (C,P,F) steckt in den Statusbits.
 
 /* Status Bits:
 0-1: status left boom: stowed/deployed
 2-3: status right boom: stowed/deployed
 4:  status boom cameras: on/off
 5:  Status Hose Clamp: sep./not sep.
 6:  Status Clamp Ring: sep./not sep.
 7:  blossom position: locked/not-locked
 8:  status tank valve: open/closed
 9:  status Inflation control command sequence: Running/not running
 10:  status thruster valve: open/closed
 11-12: status marker LEDs: on/off, strobe
 13-15: servo status (1bit per group): off, rotating
 16:  status beacon: on/off
 17:  Checkout SCET
 18:  Pod SCET
 19:  Flight SCET
 20-24 State of Statemachine
 */
 quint32 Status_Bits;

 // Pressure sensor values - 2 values per frame because sensors are read with 10 Hz
 quint16 Tank_Line_Pressure [PRESS_LENGTH];
 quint16 Feed_Pressure [PRESS_LENGTH];
 quint16 Hose_Pressure [PRESS_LENGTH];
 quint16 EV1_Pressure [PRESS_LENGTH];
 quint16 EV2_Pressure [PRESS_LENGTH]; // Equalization Volumes

 // Accelerometers - 10 values per frame --> 50 Hz
 quint16 X_Accel [ACCEL_LENGTH];
 quint16 Y_Accel [ACCEL_LENGTH];
 quint16 Z_Accel [ACCEL_LENGTH];

 // Gyros give turn rate around the axis - 10 values per frame --> 50 Hz
 quint16 X_Rate [RATES_LENGTH];
 quint16 Y_Rate [RATES_LENGTH];
 quint16 Z_Rate [RATES_LENGTH];

 // Temperatures
 quint16 ServCon_Temp; // PCBs
 quint16 PCM_Temp;
 quint16 Tank_1_Temp; // Gas Tanks
 quint16 Tank_2_Temp;
 quint16 Tank_3_Temp;
 quint16 ICV_Temp;  // Inflation Control Vlave
 quint16 Hose_Temp;  // Balloon Hose
 quint16 EV1_Temp;  // Equalization Volumes
 quint16 EV2_Temp;
 quint16 Bat1_Temp;  // Batteries
 quint16 Bat2_Temp;
 quint16 Bat3_Temp;

 quint16 Bat_Voltage; // Battery Voltage
 quint16 Current;  // Drain Current

 quint8 sync2[SYNC_LENGTH];

}TM_ServCon_Frame;


/*
#define CAMCON_FIXED	0 //fixed sesor section size (TBD)
#define PODCON_FIXED	0 //fixed sesor section size (TBD)
#define SERVCON_FIXED	101 //fixed sesor section size (TBD)//KP: I need a non-zero sized arrray
#define SYNC_SIZE		4 //sync word size

const QString SYNC_CHAR_AS_STR = "0505";

//block types
#define CAMCON	100
#define SERVCON	101
#define PODCON	102
#define PODCAM	103
#define HOUSEKEEP	104

//Sensor data block.
//Each such block can contain any number of readings of a specific sensor
typedef struct _MSensorBlock {

       unsigned char sensorId;//a unique id number for this sensor
       int blockSize;//size of this block
       int blockNum;
       int dataSize;//size of the data array
       unsigned char *data;

} MSensorBlock;

//TM Block Header
//Holds block general infomation
typedef struct _MTMBlockHeader {

	unsigned char sync[SYNC_SIZE];
	int blockSize;//size of the whole TMBlock
	unsigned short crc; //crc16
	int blockNum;
	int blockType;
	int timeStamp; //ms since LO
       
} MTMBlockHeader;

//NOTE:
//When sending the the data block, you will have to break the send operation to parts.
//You wont be able to use sizeof(MTMBlock) because of the data pointers, both in the dynamic section
//of the MTMDataBlock and in the MSensorBlock.
//When sending, you will have to iterate through the stuct elements, and send them idividually.
//When sending the dynamic data part of the MTMDataBlock you can sent it in one iteration thanks to the 'dynSize' element.
//However, if the dynamic section is empty (i.e dnynamic=NULL) there is a way to send the datablock in one iteration - ask me if
//if it gets relevan. (just using sizeof() wont do, becasue of the 'data' section in the sensor struct)

typedef struct _MTMBlock {

       MTMBlockHeader header;//the fixed part of the block
       MSensorBlock fixed[SERVCON_FIXED];  //this is an example for the servcon, in camcon the array will use CAMCON_FIXED
       int dynSize;//size of dynamic data - NOTE: you can't use sizeof(MSensorBlock)*numSensors to calculate the the size of the dynamic part//because 'data' is a pointer - you will have to count at allocation time.
       MSensorBlock *dynamic;       //the dynamic part of the block

} MTMBlock;
*/
QDataStream & operator<<(QDataStream &s, TM_ServCon_Frame& frame);
QDataStream & operator>>(QDataStream &s, TM_ServCon_Frame& frame);

} //namespace TM
#endif
